home *** CD-ROM | disk | FTP | other *** search
- /* RectToAddress
- Finds the memory address of a pixel in a PixMap or BitMap. Completely general:
- multiple screens, on or off-screen, BitMaps, PixMaps, and any pixel size.
- Doesn't require color quickdraw. The optional parameters return the row length
- of the pixmap or bitmap, the pixel size, and the offset in bits into the byte
- (for pixels that are smaller than a byte).
-
- The returned address corresponds to the upper-left pixel in *myRectPtr in *myPixMapPtr.
- If it's an off-screen Pix/BitMap clips *myRectPtr to the PixMap bounds;
- if it's on-screen clips *myRectPtr to that screen device. Returns NULL if
- *myRectPtr is empty after clipping.
-
- Note that many video cards have video memory that is only accessible when your computer
- is in 32-bit addressing mode, so you should only access the address returned by
- RectToAddress inside a block of code that operates in 32-bit addressing mode.
- Use SwapMMUMode(), which is documented in Apple's Inside Macintosh.
-
- Copyright ©1989-1993 Denis G. Pelli.
-
- HISTORY:
- 4/89 dgp v. 1.0 extracted it from CopyBitsQuickly.
- 2/91 dgp v. 1.1 no longer requires color quickdraw.
- 4/5/91 dgp v. 1.2 fixed overflow bug reported by Brady Duga.
- 8/24/91 dgp Made compatible with THINK C 5.0.
- 4/27/92 dgp Though I haven't experienced any problems I took the advice of Apple's
- Inside Mac VI and now get the pixmap base address by means of the new
- GetPixBaseAddr() if that trap is available.
- 7/13/92 dgp enhanced the documentation above. Removed support for THINK C version 4.
- 1/11/93 dgp only call GetPixBaseAddr() for PixMap, not for BitMap.
- 2/7/93 dgp return NULL if supplied pix/bitmap pointer is NULL.
- 3/14/93 dgp Use GetPixBaseAddr() only if the working version is present, i.e.
- not the first version of 32-bit QuickDraw.
- */
- #include "VideoToolbox.h"
-
- unsigned char *RectToAddress(PixMap *myPixMapPtr,Rect *myRectPtr,short *myRowBytesPtr,
- short *myPixelSizePtr,short *bitsOffsetPtr)
- /*
- *myPixMapPtr is the PixMap or BitMap that you're working in.
- *myRectPtr is the Rect you're interested in, in local coordinates.
- Will be clipped by device bounds.
- *myRowBytesPtr optionally returns rowBytes.
- *myPixelSizePtr optionally returns pixelSize.
- *bitsOffsetPtr optionally returns positive offset in bits from returned
- byte address to the location specified by upper left corner of myRectPtr
- */
- {
- GDHandle device,mainDevice;
- Rect rect,smallRect;
- register Ptr address;
- int notEmpty;
- int x0,y0;
- long qD;
-
- if(myPixMapPtr==NULL)return NULL;
- Gestalt(gestaltQuickdrawVersion,&qD);
- x0=myPixMapPtr->bounds.left;
- y0=myPixMapPtr->bounds.top;
- if(qD>=gestalt8BitQD)mainDevice=GetMainDevice();
- else mainDevice=NULL;
- // GetPixBaseAddr() did not work in the first version of 32-bit QuickDraw
- if(qD>=gestalt32BitQD12 && myPixMapPtr->rowBytes & 0x8000)
- address=GetPixBaseAddr(&myPixMapPtr);
- else address=myPixMapPtr->baseAddr;
- if(address==NULL)return NULL;
- if(mainDevice != NULL && address == (*(*mainDevice)->gdPMap)->baseAddr){
- /* When there are multiple screens, all windows refer to main device PixMap */
- /* so we have to figure out which is the actual device. */
- rect = *myRectPtr;
- OffsetRect(&rect,-x0,-y0); /* convert to global coordinates */
- /* Find device that displays the upper left pixel */
- smallRect = rect;
- smallRect.bottom=smallRect.top+1;
- smallRect.right=smallRect.left+1;
- device = GetMaxDevice(&smallRect);
- if(device==NULL)return NULL;
- myPixMapPtr = *(*device)->gdPMap; /* Use the DEVICE'S PixMap */
- // GetPixBaseAddr() did not work in the first version of 32-bit QuickDraw
- if(qD>=gestalt32BitQD12)address=GetPixBaseAddr(&myPixMapPtr);
- else address=myPixMapPtr->baseAddr;
- notEmpty=SectRect(&rect,&myPixMapPtr->bounds,&rect);
- if(!notEmpty) return NULL;
- *myRectPtr=rect;
- OffsetRect(myRectPtr,x0,y0); /* convert back to local coordinates */
- /* convert to device coordinates */
- OffsetRect(&rect,-(*device)->gdRect.left,-(*device)->gdRect.top);
- }
- else {
- /* Just clip and convert to global coordinates */
- rect = *myRectPtr;
- notEmpty=SectRect(&rect,&myPixMapPtr->bounds,&rect);
- if(!notEmpty) return NULL;
- OffsetRect(&rect,-x0,-y0); /* convert to global coordinates */
- }
- address += rect.top*(long)(myPixMapPtr->rowBytes & 0x1fff);
- if(myPixMapPtr->rowBytes & 0x8000){ /* Pixmap or Bitmap? */
- /* Pixmap */
- address += (rect.left*(long)myPixMapPtr->pixelSize)/8;
- if(bitsOffsetPtr != NULL) *bitsOffsetPtr=(rect.left*(long)myPixMapPtr->pixelSize)%8;
- if(myPixelSizePtr != NULL) *myPixelSizePtr=myPixMapPtr->pixelSize;
- }
- else{
- /* Bitmap */
- address += rect.left/8;
- if(bitsOffsetPtr != NULL) *bitsOffsetPtr=rect.left%8;
- if(myPixelSizePtr != NULL) *myPixelSizePtr=1;
- }
- if(myRowBytesPtr != NULL) (*myRowBytesPtr)=myPixMapPtr->rowBytes & 0x1fff;
- return (unsigned char *) address;
- }
-